package se.webbzon.boltzmann.game.sequence;

import se.webbzon.boltzmann.environment.AbstractEnvironment;
import se.webbzon.boltzmann.environment.PlayerEnvironment;

public class Sequences {
	
	// The prefixes used for local and environment variables
	public static final String environmentPrefix = "$";
	public static final String localPrefix = "@";
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Returns the provided variable name without the variable
	 * prefix. **/
	public static final String withoutPrefix(String str) {
		if (str.startsWith(environmentPrefix) || str.startsWith(localPrefix))
			return str.substring(1);
		else
			return str;
	}
	
	/** Returns the provided variable name with the variable
	 * prefix. **/
	public static final String withPrefix(String str, boolean local) {
		if (str.startsWith(localPrefix) || str.startsWith(environmentPrefix))
			return str;
		else if (local)
			return localPrefix + str;
		else
			return environmentPrefix + str;
	}
	
	/** Returns true if there is a variable defined with the given name. **/
	public static boolean isVariable(Sequence sequence, String name) {
		if (name.startsWith(environmentPrefix)) {
			AbstractEnvironment env = sequence.getEnvironment();
			if (env instanceof PlayerEnvironment) {
				PlayerEnvironment penv = (PlayerEnvironment) env;
				return penv.getVariables().isAssigned(withoutPrefix(name));
			} else
				return false;
		} else
			return sequence.getVariables().isAssigned(withoutPrefix(name));
	}
	
	/** Sets the variable with the given name to the provided string value. **/
	public static void set(Sequence sequence, String name, String value) {
		if (name.startsWith(environmentPrefix)) {
			AbstractEnvironment env = sequence.getEnvironment();
			if (env instanceof PlayerEnvironment) {
				PlayerEnvironment penv = (PlayerEnvironment) env;
				penv.getVariables().assign(withoutPrefix(name), value);
			}
		} else try {
			String keyName = withoutPrefix(name);
			SequenceKey key = SequenceKey.valueOf(keyName.toUpperCase());
			key.set(sequence, value);
		} catch (IllegalArgumentException e) {
			sequence.getVariables().assign(withoutPrefix(name), value);
		}
	}
	
	/** Sets the variable with the given name to the provided double value. **/
	public static void set(Sequence sequence, String name, Double value) {
		if (name.startsWith(environmentPrefix)) {
			AbstractEnvironment env = sequence.getEnvironment();
			if (env instanceof PlayerEnvironment) {
				PlayerEnvironment penv = (PlayerEnvironment) env;
				penv.getVariables().assign(withoutPrefix(name), value);
			}
		} else try {
			String keyName = withoutPrefix(name);
			SequenceKey key = SequenceKey.valueOf(keyName.toUpperCase());
			key.set(sequence, value);
		} catch (IllegalArgumentException e) {
			sequence.getVariables().assign(withoutPrefix(name), value);
		}
	}
	
	/** Parses the provided string into a value. **/
	public static final Object parse(Sequence sequence, String str) {
		if (str.isEmpty())
			return null;
		String name = withoutPrefix(str);
		if (name.isEmpty()) 
			return null;
		else if (str.startsWith(localPrefix)) {
			// Read local and special variables
			try {
				SequenceKey key = SequenceKey.valueOf(name.toUpperCase());
				return key.get(sequence);
			} catch (IllegalArgumentException e) {
				return sequence.getVariables().valueOf(name);
			}
		} else if (str.startsWith(environmentPrefix)) {
			// Read environment variables
			AbstractEnvironment env = sequence.getEnvironment();
			if (env instanceof PlayerEnvironment) {
				PlayerEnvironment penv = (PlayerEnvironment) env;
				if (penv.getVariables().isAssigned(name)) {
					return penv.getVariables().valueOf(name);
				}
			}
		}
		
		// Parse the string as a value
		try {
			return Double.parseDouble(str);
		} catch (NumberFormatException e) {
			return str;
		}
	}

}
